<?php

namespace Yolo\Utils;

use CURLFile;
use Exception;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\RequestOptions;
use Hyperf\Guzzle\CoroutineHandler;
use RuntimeException;

class Network
{
    /**
     * @param $file
     * @param array $options
     * @return array
     * @throws Exception
     */
    public static function uploadFile($file, array $options = [
        'serverUrl' => '',
        'field' => 'file',
        'args' => []
    ]): array {

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $options['serverUrl']);
        curl_setopt($ch, CURLOPT_POST, 1);

        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $file);
        finfo_close($finfo);
        $cfile = new CURLFile($file, $mimeType, basename($file));

        $postFields = $options['args'] ?? [];
        $postFields[$options['field']] = $cfile;

        curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将curl_exec()获取的信息以字符串返回，而不是直接输出

        // 启用详细模式以获取更多信息
//        curl_setopt($ch, CURLOPT_VERBOSE, true);
//        $verboseLog = fopen('php://temp', 'w+');
//        curl_setopt($ch, CURLOPT_STDERR, $verboseLog);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if ($response === false) {
            // 如果cURL出错，打印错误信息
            throw new Exception('cURL Error: ' . curl_error($ch));
        } else {

            $data = json_decode($response, true);

            if ($httpCode !== 200) {
                throw new Exception('HTTP Error: ' . $httpCode . ', message: ' . $response);
            }
        }
//
//        rewind($verboseLog);
//        $verboseLogContent = stream_get_contents($verboseLog);
//        echo "Verbose information:\n" . $verboseLogContent;
//        fclose($verboseLog);

        curl_close($ch);

        return $data;
    }

    public static function downloadFile($url, $filePath): void
    {
        try {
            $client = new GuzzleClient([
                'handler' => HandlerStack::create(new CoroutineHandler()),
                'timeout' => 30,
            ]);

            $response = $client->request('GET', $url, [
                RequestOptions::STREAM => true,
            ]);

            // 确保响应成功
            if ($response->getStatusCode() !== 200) {
                throw new RuntimeException("Failed to download file: HTTP status " . $response->getStatusCode());
            }

            // 打开一个文件指针用于写入
            $fileStream = fopen($filePath, 'w+');
            if (!$fileStream) {
                throw new RuntimeException("Failed to open local file for writing.");
            }

            // 获取响应体的流
            $stream = $response->getBody();

            while (!$stream->eof()) {
                // 每次读取8192字节(8KB)，可以根据实际情况调整大小
                fwrite($fileStream, $stream->read(8192));
            }

        } finally {
            // 确保即使发生异常也会尝试关闭文件指针
            if (isset($fileStream)) {
                fclose($fileStream);
            }
        }
    }
}
